package com.rc.saas.tenant.controller.tenant;

import com.rc.saas.tenant.base.TenantBaseController;
import com.rc.saas.tenant.common.base.HttpConstant;
import com.rc.saas.tenant.common.constant.ShiroConstants;
import com.rc.saas.tenant.common.vo.TResponse;
import com.rc.saas.tenant.config.UpYunConfig;
import com.rc.saas.tenant.model.tenant.Tenant;
import com.rc.saas.tenant.model.tenant.TenantUser;
import com.rc.saas.tenant.service.tenant.TenantMenuService;
import com.rc.saas.tenant.service.tenant.TenantService;
import com.rc.saas.tenant.service.tenant.TenantUserService;
import com.rc.saas.tenant.shiro.CustomRealm;
import com.rc.saas.tenant.vo.tenant.TenantVo;
import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.mgt.RealmSecurityManager;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.util.Date;

/**
 * 龙城充：http://localhost:8081/login?spm=gh_636245b24e64 登录帐号:19165773983 123456
 * 运营商+分销商+企业帐户登录功能处理
 */
@Controller
@RequestMapping("/")
public class LoginController extends TenantBaseController {
    private static Logger logger = LogManager.getLogger(LoginController.class);

    @Autowired
    private UpYunConfig upYunConfig;

    @Autowired
    private TenantService tenantService;

    @Autowired
    private TenantUserService tenantUserService;

    @Autowired
    private TenantMenuService tenantMenuService;

    /**
     * 跳转到登录页面
     * @return
     */
    @RequestMapping(value = "/login", method = RequestMethod.GET)
    public String login(HttpSession session, Model model) {
        //根据运商商显示不同的LOGO
        String spm = (String) session.getAttribute("spm");
        if (StringUtils.isNotBlank(spm)) {
            //String configuration = (String) redisTemplate.opsForValue().get(MessageFormat.format(SessionConstants.CACHE_WXCONFIG_TEMP, spm));
            //logger.warn("读取REDIS RedisWxConfiguration,:{},:{}", MessageFormat.format(SessionConstants.CACHE_WXCONFIG_TEMP, spm), configuration);
            Tenant tenant = tenantService.selectByOriginalid(spm);
            if (tenant != null) {
                //RedisWxConfiguration conf = JSON.parseObject(configuration, RedisWxConfiguration.class);
                //TODO
                //model.addAttribute("tenantLogoImg", upYunConfig.getDownloadRoot() + "/399306297/image/2020010709501131.png");
                //logger.warn("tenantLogoImg:{}", upYunConfig.getDownloadRoot() + "/399306297/image/2020010709501131.png");

                TenantVo tenantVo = new TenantVo();
                tenantVo.setTenantCode(tenantVo.getTenantCode());
                tenantVo.setTenantName(tenant.getWechatName());
                tenantVo.setTenantLogoImg(upYunConfig.getDownloadRoot() + tenant.getTenantLogoImg());

                model.addAttribute("tenant", tenantVo);
            } else {
                logger.info("无效的SPM:{}", spm);
            }
        }

        return "/login";
    }

    /**
     * 登录处理
     * @param model
     * @param username
     * @param password
     * @return
     */
    @RequestMapping(value = "/goLoginning", method = RequestMethod.POST)
    @ResponseBody
    public TResponse goLoginning(HttpServletRequest request, HttpSession session, Model model,
                                 String username, String password, String verify) {
        // 获取session中的验证码
        String kaptchaExpected = (String) session.getAttribute(HttpConstant.KAPTCHA_SESSION_KEY);
        logger.warn("获取session中的验证码,kaptchaExpected:{},input verify:{}", kaptchaExpected, verify);

        // 验证码不匹配
        String error = null;
        if (!verify.equalsIgnoreCase(kaptchaExpected)) {
            error = "验证码不匹配";
            model.addAttribute("login_error", error);
            //return "login";
            return TResponse.FAIL("验证码不匹配");
        }

        try {
            UsernamePasswordToken token = new UsernamePasswordToken(username, password);

            Subject subject = SecurityUtils.getSubject();
            //交由CustomRealm.doGetAuthenticationInfo 方法校验,执行登陆
            subject.login(token);

            //TenantUserExample example = new TenantUserExample();
            //example.createCriteria().andLoginNameEqualTo(token.getUsername());
            TenantUser user = tenantUserService.selectByLoginName(token.getUsername());

            if (!"0".equals(user.getStatus())) {
                error = "用户不是启用状态";
            } else {
                //更新登录信息表
                TenantUser updateUser = new TenantUser();
                updateUser.setTenantUserId(user.getTenantUserId());
                updateUser.setLastLoginTime(new Date());

                String clientIp = request.getRemoteAddr();
                updateUser.setLastLoginIp(clientIp);
                tenantUserService.updateByPrimaryKeySelective(updateUser);

                //使用shiro的session保存,使用时直接用HttpSession.getAttribute(key)就可以取到
                //save session object into shiro-session
                subject.getSession().setAttribute(ShiroConstants.SESSION_TENANT_USER_KEY, user);

                logger.info("登录成功:{},:{}", username, subject.getSession().getId());
            }
        } catch (UnknownAccountException | IncorrectCredentialsException e) {
            // error = "用户名或密码不匹配";
            return TResponse.FAIL("用户名或密码不匹配");
        } catch (AuthenticationException e) {
            // error = "登录异常，请重新登录";
            return TResponse.FAIL("登录异常，请重新登录");
        }

        // 出错了，返回登录页面
        if (error != null) {
            model.addAttribute("login_error", error);
            return TResponse.FAIL("该用户已被冻结");
            // return "/login";
        }
        return TResponse.SUCCESS();
        //  return "redirect:/welcome";
    }

    /**
     * 自定义退出
     * @return
     */
    @RequestMapping(value = "/goLogout", method = RequestMethod.GET)
    public String goLogout(HttpServletRequest request) {
        //根据运商商显示不同的LOGO
        String spm = (String) request.getSession().getAttribute("spm");

        Subject subject = SecurityUtils.getSubject();
        //logout后shiro会自动创建一个session(此session不等于在线用户)
        SecurityUtils.getSubject().logout();
        logger.info("登出成功1:{}", subject.getSession().getId());

        //删除授权缓存
        RealmSecurityManager rsm = (RealmSecurityManager) SecurityUtils.getSecurityManager();
        CustomRealm realm = (CustomRealm) rsm.getRealms().iterator().next();
        realm.clearAllCache();

        //RedisSessionDAO sessionDAO = (RedisSessionDAO) getBean("redisSessionDAO");
        //Session session = sessionDAO.readSession(sessionId);
        //if (session != null) {
        //    session.setAttribute("kickout", Boolean.TRUE); //设置会话的kickout属性表示踢出了
        //    session.setTimeout(0L); //设置session立即失效，即将其踢出系统break;
        //    session.stop(); //销毁Shiro的会话
        //    sessionDAO.delete(session);
        //}

        //删除会话
        Subject subject2 = SecurityUtils.getSubject();
        //Serializable session = "admin:shiro:session:" + subject.getSession().getId();

        //subject.getSession().removeAttribute(session);
        //RedisSessionDAO sessionDAO = (RedisSessionDAO) getBean("redisSessionDAO");

        //admin:shiro:session:e5db257a-7ba7-4ba9-9ae8-01cf7547f263
        //sessionDAO.delete(subject.getSession());

        logger.info("登出成功2:{}", subject2.getSession().getId());

        //带着SPM参数跳转
        if (StringUtils.isNotBlank(spm)) {
            return "redirect:/login?spm=" + spm;
        } else {
            return "/login";
        }
    }
}